package com.ruihu.admin.module.system.role.roleuser;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruihu.admin.common.domain.PageResultDTO;
import com.ruihu.admin.module.system.department.DepartmentService;
import com.ruihu.admin.module.system.department.dao.DepartmentDao;
import com.ruihu.admin.module.system.department.domain.entity.DepartmentEntity;
import com.ruihu.admin.module.system.department.domain.vo.DepartmentVO;
import com.ruihu.admin.module.system.role.basic.domain.dto.RoleUserBatchDTO;
import com.ruihu.admin.module.system.role.roleuser.dao.RoleUserDao;
import com.ruihu.admin.module.system.role.roleuser.domain.RoleUserDTO;
import com.ruihu.admin.module.system.user.dao.UserDao;
import com.ruihu.admin.module.system.user.domain.dto.UserDTO;
import com.ruihu.admin.module.system.user.domain.entity.UserEntity;
import com.ruihu.admin.module.system.user.domain.vo.UserVO;
import com.ruihu.admin.module.system.role.basic.dao.RoleDao;
import com.ruihu.admin.module.system.role.basic.domain.dto.RoleBatchDTO;
import com.ruihu.admin.module.system.role.basic.domain.dto.RoleQueryDTO;
import com.ruihu.admin.module.system.role.basic.domain.dto.RoleSelectedVO;
import com.ruihu.admin.module.system.role.basic.domain.entity.RoleEntity;
import com.ruihu.admin.module.system.role.roleuser.domain.RoleUserEntity;
import com.ruihu.admin.util.BeanUtil;
import com.ruihu.admin.util.PageUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 角色管理业务
 *
 * @author zzr
 * @date 2019/4/3
 */
@Service
public class RoleUserService {

    @Autowired
    private RoleUserDao roleUserDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private UserDao userDao;

    /**
     * 通过角色id，分页获取用户列表
     *
     * @param queryDTO
     * @return
     */
    public PageResultDTO<UserVO> listUserByName(RoleQueryDTO queryDTO) {
        IPage<RoleUserEntity> iPage = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        QueryWrapper<RoleUserEntity> queryWrapper = new QueryWrapper<>();
        if(StringUtils.isNotEmpty(queryDTO.getRoleId())){
            queryWrapper.eq("role_id",queryDTO.getRoleId());
        }
        roleUserDao.selectPage(iPage,queryWrapper);
        IPage<RoleUserEntity> roleUserEntityIPage = roleUserDao.selectPage(iPage, queryWrapper);
        if (Objects.isNull(iPage) || CollectionUtils.isEmpty(iPage.getRecords())) {
            return new PageResultDTO<>();
        }
        List<Long> userIds = roleUserEntityIPage.getRecords().stream().map(x->x.getUserId()).collect(Collectors.toList());
        QueryWrapper<UserEntity> userEntityQueryWrapper = new QueryWrapper<>();
        userEntityQueryWrapper.in("id",userIds);
        List<UserEntity> users = userDao.selectList(userEntityQueryWrapper);
        List<Long> departmentIds = users.stream().filter(e -> e.getDepartmentId() != null).map(x->x.getDepartmentId()).collect(Collectors.toList());
        List<DepartmentVO> departmentVOS = departmentService.queryDepartmentsByIds(departmentIds);
        List<UserDTO> userDTOS = users.stream().map(x->buildUserDTO(x, CollectionUtils.isEmpty(departmentVOS) ? new HashMap<>() :
                departmentVOS.stream().collect(Collectors.toMap(DepartmentVO::getId , v->v)))).collect(Collectors.toList());
        PageResultDTO<UserVO> pageResultDTO = PageUtil.convert2PageResult(iPage, userDTOS, UserVO.class);
        return pageResultDTO;
    }

    public List<UserVO> getAllUserByRoleId(Long roleId) {
        List<UserDTO> userDTOS = roleUserDao.selectUserByRoleId(roleId);
        List<UserVO> list = BeanUtil.copyList(userDTOS, UserVO.class);
        return list;
    }

    public PageResultDTO<UserVO> getUserPageByRoleId(RoleQueryDTO roleQueryDTO) {
        Page<RoleUserEntity> page = PageUtil.convert2QueryPage(roleQueryDTO);
        List<UserDTO> userDTOS = roleUserDao.selectUserByRoleIdPage(page, Long.parseLong(roleQueryDTO.getRoleId()));
        List<UserVO> list = BeanUtil.copyList(userDTOS, UserVO.class);
        return PageUtil.convert2PageResult(page, list);
    }

    private UserDTO buildUserDTO(UserEntity userEntity,Map<Long,DepartmentVO> departmentVOMap) {
        if (userEntity == null) {
            return null;
        }
        UserDTO userDTO = new UserDTO();
        userDTO.setUsername(userEntity.getUsername());
        userDTO.setWorkNo(userEntity.getWorkNo());
        userDTO.setUserType(userEntity.getUserType());
        userDTO.setActualName(userEntity.getActualName());
        userDTO.setNickName(userEntity.getNickName());
        userDTO.setPhone(userEntity.getPhone());
        userDTO.setIdCard(userEntity.getIdCard());
        userDTO.setDepartmentId(userEntity.getDepartmentId());
        if(departmentVOMap.containsKey(userDTO.getDepartmentId())){
            userDTO.setDepartmentName(departmentVOMap.get(userDTO.getDepartmentId()).getDepartmentName());
        }
        userDTO.setIsLeave(userEntity.getIsLeave());
        userDTO.setEmail(userEntity.getEmail());
        userDTO.setCreateUser(userEntity.getCreateUser());
        userDTO.setIsDelete(userEntity.getIsDelete());
        userDTO.setIsDisabled(userEntity.getIsDisabled());
        userDTO.setId(userEntity.getId());
        userDTO.setCreateTime(userEntity.getCreateTime());
        return userDTO;
    }

    /**
     * 移除用户角色
     *
     * @param userId
     * @param roleId
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeUserRole(Long userId, Long roleId) {
        roleUserDao.deleteByUserIdRoleId(userId, roleId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeRolesByUserId(Long userId) {
        QueryWrapper<RoleUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        roleUserDao.delete(queryWrapper);
    }

    /**
     * 批量删除角色的成员员工
     *
     * @param removeDTO
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchRemoveUserRole(RoleBatchDTO removeDTO) {
        List<Long> UserIdList = removeDTO.getUserIds();
        roleUserDao.batchDeleteUserRole(removeDTO.getRoleId(), UserIdList);
    }

    /**
     * 批量添加角色的成员员工
     *
     * @param addDTO
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchAddRoleUser(RoleBatchDTO addDTO) {
        Long roleId = addDTO.getRoleId();
        List<Long> UserIdList = addDTO.getUserIds();
        List<RoleUserEntity> roleRelationEntities = Lists.newArrayList();
        RoleUserEntity UserRoleRelationEntity;
        for (Long UserId : UserIdList) {
            UserRoleRelationEntity = new RoleUserEntity();
            UserRoleRelationEntity.setRoleId(roleId);
            UserRoleRelationEntity.setUserId(UserId);
            roleRelationEntities.add(UserRoleRelationEntity);
        }
        roleUserDao.batchInsert(roleRelationEntities);
    }

    public void batchAddUserRole(RoleUserBatchDTO addDTO) {
        Long userId = addDTO.getUserId();
        roleUserDao.deleteByUserId(userId);
        List<RoleUserEntity> roleRelationEntities = Lists.newArrayList();
        RoleUserEntity UserRoleRelationEntity;
        for (Long roleId : addDTO.getRoleIds()) {
            UserRoleRelationEntity = new RoleUserEntity();
            UserRoleRelationEntity.setRoleId(roleId);
            UserRoleRelationEntity.setUserId(userId);
            roleRelationEntities.add(UserRoleRelationEntity);
        }
        roleUserDao.batchInsert(roleRelationEntities);
    }

    /**
     * 通过用户id获取用户角色
     *
     * @param userId
     * @return
     */
    public List<RoleSelectedVO> getRolesByUserId(Long userId) {
        List<Long> roleIds = roleUserDao.selectRoleIdByUserId(userId);
        List<RoleEntity> roleList = roleDao.selectList(null);
        List<RoleSelectedVO> result = BeanUtil.copyList(roleList, RoleSelectedVO.class);
        result.stream().forEach(item -> item.setSelected(roleIds.contains(item.getId())));
        return result;
    }

    /**
     * 添加角色的成员员工
     *
     * @param dto
     * @return ResponseDTO<String>
     */
    @Transactional(rollbackFor = Exception.class)
    public Long insertUserRole(RoleUserDTO dto){
        RoleUserEntity roleUserEntity = new RoleUserEntity();
        roleUserEntity.setRoleId(dto.getRoleId());
        roleUserEntity.setUserId(dto.getUserId());
        int count = roleUserDao.insert(roleUserEntity);
        if(count==1){
            return roleUserEntity.getId();
        }
        return null;
    }

    /**
     * 根据userId查询角色Id
     * @param id
     * @return
     */
    public List<Long> queryRolesByUserId(Long id) {
        return  roleUserDao.selectRoleIdByUserId(id);
    }

    /**
     * 根据userId删除角色
     * @param userId
     */
    public void deleteByUserId(Long userId) {
        roleUserDao.deleteByUserId(userId);
    }


    /**
     * 批量查询用户角色
     * @param userIds
     */
    public Map<Long,List<Long>> queryRolesByUserIds(List<Long> userIds){
        QueryWrapper<RoleUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id",userIds);
        List<RoleUserEntity> roleUserList = roleUserDao.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(roleUserList)){
            return null;
        }
        Map<Long,List<Long>> map = roleUserList.stream()
                .collect(Collectors.groupingBy(
                        RoleUserEntity::getUserId,
                        Collectors.mapping(RoleUserEntity::getRoleId, Collectors.toList())));
        return map;
    }
}
